
#pragma once


/* Design:
	At the moment we're using RTTI to Retrieve states. Alternatives would be to use
	a string to identify each state, or to use an enum to identify each state.
	Taking one of these approaches would require more code, but would make it possible
	to ensure that states are unique, and it might have additional benefits.
*/


#include <boost/any.hpp>
#include <vector>

#include "Singleton.h"
#include "IGameState.h"

//! This class stores all the created states.
//!
//! @remark States should be unique.
class StateRegistry : public Shared::Singleton<StateRegistry>
{
	std::vector<IGameState*> mStates;

public:

	//! Destructs the state registry.
	//!
	virtual ~StateRegistry() {}

	//! Registers a state.
	//!
	void Add(IGameState * gameState)
	{
		mStates.push_back(gameState);
	}

	//! Retrieves a state. Returns 0 if the state is not found.
	//!
	//! @remark Linear time. Uses RTTI.
	//!
	template <class T>
	T * Retrieve()
	{
		T * ret = 0;

		for(std::vector<IGameState*>::iterator it = mStates.begin(); 
			it != mStates.end(); ++it)
		{
			ret = dynamic_cast<T*>(*it);
			if(ret)
				break;
		}

		return ret;
	}

	//! Retrieves a state reference. Throws a bad_cast if the state is not found.
	//!
	//! @remark Linear time. Uses RTTI.
	//!
	template <class T>
	T & RetrieveRef()
	{
		T * ret = Retrieve<T>();

		if(!ret)
			throw std::bad_cast("Could not find state.");
		return *ret;
	}

};